<template>
  <div class="hue" @mousedown.prevent.stop="selectHue">
    <canvas ref="canvasHueRef" />
    <div :style="attr.slideHueStyle" class="slide" />
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from "vue"
const props = defineProps({
  hsv: {
    type: Object,
    default: null,
  },
  width: {
    type: Number,
    default: 15,
  },
  height: {
    type: Number,
    default: 152,
  },
})
const emit = defineEmits(["selectHue"])
const canvasHueRef = ref()
const attr = reactive({
  slideHueStyle: {},
})
onMounted(() => {
  renderColor()
  renderSlide()
})
const renderColor = () => {
  const canvas: any = canvasHueRef.value
  const width = props.width
  const height = props.height
  const ctx = canvas.getContext("2d")
  canvas.width = width
  canvas.height = height

  const gradient = ctx.createLinearGradient(0, 0, 0, height)
  gradient.addColorStop(0, "#FF0000") // red
  gradient.addColorStop(0.17 * 1, "#FF00FF") // purple
  gradient.addColorStop(0.17 * 2, "#0000FF") // blue
  gradient.addColorStop(0.17 * 3, "#00FFFF") // green
  gradient.addColorStop(0.17 * 4, "#00FF00") // green
  gradient.addColorStop(0.17 * 5, "#FFFF00") // yellow
  gradient.addColorStop(1, "#FF0000") // red
  ctx.fillStyle = gradient
  ctx.fillRect(0, 0, width, height)
}
const renderSlide = () => {
  attr.slideHueStyle = {
    top: (1 - props.hsv.h / 360) * props.height - 2 + "px",
  }
}

const selectHue = (e: any) => {
  const { top: hueTop } = canvasHueRef.value.getBoundingClientRect()
  const ctx = e.target.getContext("2d")
  const mousemove = (e: any) => {
    let y = e.clientY - hueTop
    if (y < 0) {
      y = 0
    }
    if (y > props.height) {
      y = props.height
    }
    attr.slideHueStyle = {
      top: y - 2 + "px",
    }
    const imgData = ctx.getImageData(0, Math.min(y, props.height - 1), 1, 1)
    const [r, g, b] = imgData.data
    emit("selectHue", { r, g, b })
  }
  mousemove(e)
  const mouseup = () => {
    document.removeEventListener("mousemove", mousemove)
    document.removeEventListener("mouseup", mouseup)
  }
  document.addEventListener("mousemove", mousemove)
  document.addEventListener("mouseup", mouseup)
}
defineExpose({renderSlide})
</script>

<style scoped lang="scss">
.hue {
  position: relative;
  margin-left: 8px;
  cursor: pointer;
  .slide {
    position: absolute;
    left: 0;
    top: 100px;
    width: 100%;
    height: 4px;
    background: #fff;
    box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.3);
    pointer-events: none;
  }
}
</style>
